package ai.phase.cognition.development;
import ai.*;
import java.util.*;


public class SimpleAgent implements MapAgent{

	
	
	
	Hashtable<Integer, RegionModel> j_RegionIndexModelMap;
	AgentGenome j_Genes;
	LinkedList<ActionPointer> j_APList;
	AgentState j_CurrentState;
	Hashtable<String, AgentState> j_StateMap;
	Integer j_ChosenAction;
	RegionModel j_CurrentRegion;
	RegionModel j_PriorRegion;
	Integer j_CurrentRegionIndex;
	Integer j_PriorRegionIndex;
	int[] j_AvailableActions;
	int j_CurrentUtility;
	int j_PreviousAction;
	
	public SimpleAgent(AgentGenome genes)
	{
		j_Genes=genes;
		j_StateMap=  new Hashtable<String, AgentState>();
		j_APList = new LinkedList<ActionPointer>();
	}
	
	public Integer UpdateCurrentState(int currentRegionId, int[] currentAvailableActions,int currentUtility, int stepMilli)
	{
		// While 
		j_ChosenAction=null;
		j_AvailableActions=currentAvailableActions;
		j_CurrentUtility=currentUtility;
		j_CurrentRegionIndex=currentRegionId;
		long startTimeMilli = System.currentTimeMillis();
		long stopTimeMilli = startTimeMilli+stepMilli;
		// check if 
		
		
		while (System.currentTimeMillis()<stopTimeMilli)
		{
			j_CurrentState = j_CurrentState.GetNextState(null);
		}
		j_PriorRegionIndex=j_CurrentRegionIndex;
		return j_ChosenAction;
	}
	
	private void InitializeStates()
	{
		// 
		AgentState state;
		// Define initial state
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				
				j_APList = new LinkedList<ActionPointer>();
				return j_StateMap.get("INITIAL-STATE");
			}
		};
		j_StateMap.put("RESET", state);
		
		
		// Define initial state
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				
				return j_StateMap.get("CHECKING-IF-AP-LIST-EMPTY");
			}
		};
		j_StateMap.put("INITIAL-STATE", state);
		
		// Define checking if ap list empty
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				if (j_APList.size()==0)
				{
					return j_StateMap.get("CHOOSING-GOAL-REGION");
				}
				else
					return j_StateMap.get("PROCESS-NEXT-ACTION-POINTER");
				 
			}
		};
		j_StateMap.put("CHECKING-IF-AP-LIST-EMPTY", state);
		
		// Processing next action pointer
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				ActionPointer ap;
				ap=j_APList.removeFirst();
				j_ChosenAction=ap.GetActionId();
				return j_StateMap.get("CHECKING-IF-REGION-INDEX-EXISTS"); 
			}
		};
		j_StateMap.put("PROCESS-NEXT-ACTION-POINTER", state);
		
		// Checking for prior region model
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				if (j_PriorRegion==null)
					return j_StateMap.get("CHECKING-IF-CURRENT-REGION-INDEX-EXISTS");
				else
					return j_StateMap.get("FINISH-UPDATING-PREVI0US-REGION-MODEL");
			}
		};
		j_StateMap.put("CHECKING-FOR-PRIOR-REGION-MODEL", state);
		
		// Checking if current region index exists
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				if (j_RegionIndexModelMap.containsKey(j_CurrentRegionIndex))
				{
					j_CurrentRegion=j_RegionIndexModelMap.get(j_CurrentRegionIndex);
					
				}
				else
				{
					// Now you can't resolve the current region yet.  This depends on whether there is a previous region 
					j_CurrentRegion = null; 
					// Cleare action pointer list because this can only be true if you've either reached your
					// destination or are lost, in either case, AP list must be reset
					j_APList = new LinkedList<ActionPointer>();
				}
				return j_StateMap.get("CHECKING-FOR-PRIOR-REGION-MODEL");
			}
		};
		j_StateMap.put("CHECKING-IF-REGION-INDEX-EXISTS", state);
		
		// Checking for prior regions.  
		state= new AgentState()
		{
			public AgentState GetNextState(Object eventData)
			{
				if (j_PriorRegion==null)
				{// starting for first time
					
					// create new non-virtual region
					j_CurrentRegion= new RegionModel(j_CurrentRegionIndex);
					j_RegionIndexModelMap.put(j_CurrentRegionIndex, j_CurrentRegion);
					CreateVirtualRegions(j_CurrentRegion,j_AvailableActions);
					
				}
				else
				{
					// Prior region exists, check if current region could be resolved
					if (j_CurrentRegion==null)
					{
						// Current region is the previous virtual region that was mapped 
						// to prior action
						//
						j_CurrentRegion=j_PriorRegion.GetMappedRegion(j_PreviousAction);
						j_CurrentRegion.SetRegionIndex(j_CurrentRegionIndex);
						CreateVirtualRegions(j_CurrentRegion,j_AvailableActions);
						
					}
					else
					{
						
					}
					j_PriorRegion.SetActionRegionMap(j_PreviousAction, j_CurrentRegion);
				}
			}
		};
		j_StateMap.put("CHECKING-FOR-PRIOR-REGION-MODEL", state);
	}
	
	
	// State methods
	private void CreateVirtualRegions(RegionModel currentModel, int[] adjacentActions)
	{
		for (int actionIndex:adjacentActions)
		{
			currentModel.SetActionRegionMap(actionIndex, new RegionModel());
		}
	}
	
	private void CheckForOptionMismatch()
	{
		// Need to determine what do do when there is a mismatch between the expected adjacent 
		// regions and the actual regions.  this depends on the genome
	}
	
	
	
	
}
